package hospital.action;

import hospital.model.EmpInfoModel;
import hospital.model.LoginModel;
import hospital.model.OfficeInfoModel;
import hospital.model.PatientInfoModel;
import hospital.model.UserInfoModel;
import hospital.service.AdminService;
import hospital.util.HospitalUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;

public class AdminOperation extends ActionSupport implements Preparable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -8513387765965475886L;
	private HospitalUtil hospitalUtil;
	private LoginModel loginInfo;
	private EmpInfoModel empInfo;
	private AdminService adminService;
	private String firstname;
	private String lastname;
	private String email;
	private String sin;
	private String gender;
	private String phoneNum;
	private String cellphone;
	private String address;
	private String postalCode;
	private String role;
	private String date;
	private String time;
	private String year;
	private String month;
	private String day;
	private String hour;
	private String minute;
	private String officePhone;

	private String searchUserId;
	private String searchFirstname;
	private String searchLastname;
	private List<UserInfoModel> userSearchResult;

	private String resetUserId;
	private String resetRole;

	private boolean flag;
	private String message;

	private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
			+ "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

	private static final String POSTALCODE_PATTERN = "^[A-Z]{1}\\d{1}[A-Z]{1}\\d{1}[A-Z]{1}\\d{1}$";
	private static final String PHONE_PATTERN = "\\d{10}";
	private static final String SIN_PATTERN = "\\d{9}";

	@Override
	public void prepare() throws Exception {
		clearActionErrors();
		clearFieldErrors();
	}

	public String createEmp() {
		message = "";
		flag = true;
		OfficeInfoModel office = new OfficeInfoModel();
		if (gender.equals("-1") || email.trim().equals("") || sin.trim().equals("") || firstname.trim().equals("")
				|| lastname.trim().equals("") || date.trim().equals("") || phoneNum.trim().equals("")
				|| cellphone.trim().equals("") || address.trim().equals("") || postalCode.trim().equals("")
				|| role.equals("-1") || officePhone.trim().equals("")) {
			flag = false;
			message += "All fields are required.<br />";
		}
		Pattern pattern = Pattern.compile(EMAIL_PATTERN);
		Matcher matcher = pattern.matcher(email.trim());
		Pattern patternPostal = Pattern.compile(POSTALCODE_PATTERN);
		Matcher matcherPostal = patternPostal.matcher(postalCode.trim());
		Pattern patternPhone = Pattern.compile(PHONE_PATTERN);
		Matcher matcherPhone = patternPhone.matcher(phoneNum.trim());
		Matcher matcherCellP = patternPhone.matcher(cellphone.trim());
		Matcher matcherOfficeP = patternPhone.matcher(officePhone.trim());
		Pattern patternSin = Pattern.compile(SIN_PATTERN);
		Matcher matcherSin = patternSin.matcher(sin.trim());
		if (!matcher.matches()) {
			flag = false;
			message += "The email is not valid.<br />";
		}
		if (!matcherPostal.matches()) {
			flag = false;
			message += "The postal code is not valid.<br />";
		}
		if (!matcherPhone.matches()) {
			flag = false;
			message += "The phone number is not valid.<br />";
		}
		if (!matcherCellP.matches()) {
			flag = false;
			message += "The cellphone number is not valid.<br />";
		}
		if (!matcherSin.matches()) {
			flag = false;
			message += "The Social Insurance Number is not valid.<br />";
		}
		if (!matcherOfficeP.matches()) {
			flag = false;
			message += "The office phone number is not valid.<br />";
		}
		if (!adminService.checkAvailability(email.trim())) {
			flag = false;
			message += "The email has been used.<br />";
		}
		if (!adminService.checkSinUnique(hospitalUtil.encrypt(sin.trim()))) {
			flag = false;
			message += "The Social Insurance Number has been used.<br />";
		}
		if (!adminService.checkOffice(officePhone.trim())) {
			flag = false;
			message += "The office phone number does not exist.<br />";
		} else {
			office = adminService.getOfficeInfo(officePhone.trim());
		}

		SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
		Date parsedDate = null;
		try {
			parsedDate = sdf.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
			flag = false;
			message += "Date of birth is not valid.<br />";
		}
		if (parsedDate != null) {
			Calendar c = Calendar.getInstance();
			c.setTime(parsedDate);
			if (c.getTimeInMillis() > Calendar.getInstance().getTimeInMillis()) {
				flag = false;
				message += "The date of birth should not come after the current time.<br />";
			}
		}
		if (flag == false) {
			return SUCCESS;
		}

		loginInfo.setUsername(email.trim());
		loginInfo.setPassword(hospitalUtil.encrypt(sin.trim()));
		empInfo.setRole(Byte.valueOf(role));
		empInfo.setFirstname(firstname.trim());
		empInfo.setLastname(lastname.trim());
		empInfo.setEmail(email.trim());
		if (parsedDate != null) {
			empInfo.setDateOfBirth(parsedDate);
		}
		empInfo.setSin(hospitalUtil.encrypt(sin.trim()));
		if (gender.equals("male")) {
			empInfo.setGender('m');
		} else {
			empInfo.setGender('f');
		}
		empInfo.setPhonenum(phoneNum.trim());
		empInfo.setCellphone(cellphone.trim());
		empInfo.setAddress(address.trim());
		empInfo.setPostalCode(postalCode.trim());

		empInfo.setOfficeInfo(office);

		boolean result = adminService.createEmp(loginInfo, empInfo);
		if (result) {
			flag = true;
			message = "Create the employee successfully.";
			return SUCCESS;
		} else {
			flag = false;
			message = "Fail to create the new employee.";
			return SUCCESS;
		}
	}

	public String searchResult() {
		String wrappedUserId = searchUserId.trim();
		long userId = -1;
		if (!wrappedUserId.equals("")) {
			userId = hospitalUtil.deIdWrapper(wrappedUserId, (byte) 0);
		}
		String firstname = searchFirstname.trim();
		String lastname = searchLastname.trim();
		if (userId == -1 && firstname.equals("") && lastname.equals("")) {
			userSearchResult.clear();
			return SUCCESS;
		}
		userSearchResult = adminService.getUserResult(userId, firstname, lastname);
		Iterator<UserInfoModel> it = userSearchResult.iterator();
		UserInfoModel tmp = new UserInfoModel();
		while (it.hasNext()) {
			tmp = it.next();
			userId = tmp.getUserId();
			tmp.setUserId(hospitalUtil.idWrapper(userId, tmp.getRole()));
		}
		return SUCCESS;
	}

	public String resetPassword() {
		String wrappedUserId = resetUserId.trim();
		long userId = -1;
		if (!wrappedUserId.equals("")) {
			userId = hospitalUtil.deIdWrapper(wrappedUserId, Byte.valueOf(resetRole));
		}
		boolean result = adminService.resetPassword(userId);
		if (result) {
			flag = true;
			message = "Reset password successfully.";
			return SUCCESS;
		} else {
			flag = false;
			message = "Fail to reset password.";
			return SUCCESS;
		}
	}

	public String getFirstname() {
		return firstname;
	}

	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}

	public String getLastname() {
		return lastname;
	}

	public void setLastname(String lastname) {
		this.lastname = lastname;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getSin() {
		return sin;
	}

	public void setSin(String sin) {
		this.sin = sin;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getPhoneNum() {
		return phoneNum;
	}

	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}

	public String getCellphone() {
		return cellphone;
	}

	public void setCellphone(String cellphone) {
		this.cellphone = cellphone;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getPostalCode() {
		return postalCode;
	}

	public void setPostalCode(String postalCode) {
		this.postalCode = postalCode;
	}

	public String getRole() {
		return role;
	}

	public void setRole(String role) {
		this.role = role;
	}

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	public String getTime() {
		return time;
	}

	public void setTime(String time) {
		this.time = time;
	}

	public String getYear() {
		return year;
	}

	public void setYear(String year) {
		this.year = year;
	}

	public String getMonth() {
		return month;
	}

	public void setMonth(String month) {
		this.month = month;
	}

	public String getDay() {
		return day;
	}

	public void setDay(String day) {
		this.day = day;
	}

	public String getHour() {
		return hour;
	}

	public void setHour(String hour) {
		this.hour = hour;
	}

	public String getMinute() {
		return minute;
	}

	public void setMinute(String minute) {
		this.minute = minute;
	}

	public String getOfficePhone() {
		return officePhone;
	}

	public void setOfficePhone(String officePhone) {
		this.officePhone = officePhone;
	}

	public HospitalUtil getHospitalUtil() {
		return hospitalUtil;
	}

	public void setHospitalUtil(HospitalUtil hospitalUtil) {
		this.hospitalUtil = hospitalUtil;
	}

	public EmpInfoModel getEmpInfo() {
		return empInfo;
	}

	public void setEmpInfo(EmpInfoModel empInfo) {
		this.empInfo = empInfo;
	}

	public AdminService getAdminService() {
		return adminService;
	}

	public void setAdminService(AdminService adminService) {
		this.adminService = adminService;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public LoginModel getLoginInfo() {
		return loginInfo;
	}

	public void setLoginInfo(LoginModel loginInfo) {
		this.loginInfo = loginInfo;
	}

	public String getSearchUserId() {
		return searchUserId;
	}

	public void setSearchUserId(String searchUserId) {
		this.searchUserId = searchUserId;
	}

	public String getSearchFirstname() {
		return searchFirstname;
	}

	public void setSearchFirstname(String searchFirstname) {
		this.searchFirstname = searchFirstname;
	}

	public String getSearchLastname() {
		return searchLastname;
	}

	public void setSearchLastname(String searchLastname) {
		this.searchLastname = searchLastname;
	}

	public List<UserInfoModel> getUserSearchResult() {
		return userSearchResult;
	}

	public void setUserSearchResult(List<UserInfoModel> userSearchResult) {
		this.userSearchResult = userSearchResult;
	}

	public String getResetUserId() {
		return resetUserId;
	}

	public void setResetUserId(String resetUserId) {
		this.resetUserId = resetUserId;
	}

	public String getResetRole() {
		return resetRole;
	}

	public void setResetRole(String resetRole) {
		this.resetRole = resetRole;
	}

}
